import Axios, {AxiosRequestConfig, AxiosResponse} from 'axios';
import {Loading, Message, MessageBox} from 'element-ui';
import store from '@/store';
import Qs from 'qs';
import router from '@/router';
import storeUtils from '@/utils/storeUtils';

let loadingInstance: any;


// 创建axios的实例
const service = Axios.create({
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  baseURL: process.env.VUE_APP_BASE_API, // api的base_url
  timeout: 10000, // 超时时间
  // `paramsSerializer` 是一个负责 `params` 序列化的函数
  // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  paramsSerializer(params) {
    return Qs.stringify(params, {arrayFormat: 'repeat'}); // 针对get 和 delete 方法参数序列化
  },
  transformRequest: [(params) => {
    if (params instanceof FormData) {
      return params;
    }
    if (params && params.json) {
      delete params.json;
      return JSON.stringify(params);
    }
    // 对 data 进行任意转换处理
    return Qs.stringify(params, {arrayFormat: 'repeat'}); // 针对post和put方法参数序列化
  }],
});

// 请求拦截
service.interceptors.request.use((config: AxiosRequestConfig) => {
    if ((config.params && config.params.loading === undefined) || (config.params && config.params.loading !== undefined && config.params.loading === true)) {
      delete config.params.loading;
      loadingInstance = Loading.service({fullscreen: true, background: 'rgba(0, 0, 0, 0.7)'});
    }
    // 发送请求前添加token信息
    if (store.getters.token) {  // 每次发送请求之前判断是否存在token，如果存在，则统一在http请求的header都加上token，不用每次请求都手动添加了
      (config as any).headers.Authorization = `Bearer ${store.getters.token}`;
    }
    return config;
  },
  (err: any) => {
    return Promise.reject(err);
  },
);

// 响应拦截
service.interceptors.response.use(
  (response: AxiosResponse) => {
    if (loadingInstance) {
      loadingInstance.close();
    }

    if (response.status === 200) {
      if (response.headers && response.headers.authorization) {
        store.commit('SET_TOKEN', response.headers.authorization);
      }
      if (response.data) {
        if (response.data.code === 200) {
          // 对响应数据做点什么
          return Promise.resolve(response.data);
        }
        if (response.headers['content-type'] === 'application/octet-stream;charset=UTF-8') {
          return Promise.resolve(response);
        }
      }
      if (response.headers['content-type'].includes('text/plain')) {
        return Promise.resolve(response);
      }
    }
    if ((!response.config.params || (response.config.params && (response.config.params.isShowMsg === undefined || response.config.params.isShowMsg === true))) && response.data && response.data.msg) {
      Message.warning(response.data.msg);
    }
    return Promise.reject(response.data);
  },
  (err: any) => {
    let errMsg = '';
    if (err && err.response && err.response.status) {
      switch (err.response.status) {
        case 400:
          return Promise.reject(err.response);

        case 401:
          errMsg = '登录状态失效，请重新登录';
          if (!router.currentRoute.path.startsWith('/login') && router.currentRoute.path !== '/') {
            MessageBox.confirm(
              '登录状态已过期，您可以继续留在该页面，或者重新登录',
              '系统提示',
              {
                confirmButtonText: '重新登录',
                cancelButtonText: '取消',
                type: 'warning',
              },
            ).then(() => {
              store.dispatch('FedLogOut').then(() => {
                location.reload(); // 为了重新实例化vue-router对象 避免bug
              });
            }).catch(() => {
              if (loadingInstance) {
                loadingInstance.close();
              }
            });
          } else {
            storeUtils.clearStore();
            location.reload(); // 为了重新实例化vue-router对象 避免bug
          }
          return Promise.reject(err.response);
        case 403:
          errMsg = '拒绝访问';
          break;
        case 404:
          errMsg = '请求地址不存在';
          break;

        case 408:
          errMsg = '请求超时';
          break;

        case 500:
          errMsg = '服务器内部错误';
          break;

        case 501:
          errMsg = '服务未实现';
          break;

        case 502:
          errMsg = '网关错误';
          break;

        case 503:
          errMsg = '服务不可用';
          break;

        case 504:
          errMsg = '网关超时';
          break;

        case 505:
          errMsg = 'HTTP版本不受支持';
          break;

        default:
          errMsg = err.response.data.msg;
          break;
      }
    } else {
      if (err.code === 'ECONNABORTED') {
        errMsg = '请求超时';
      } else {
        errMsg = err.message;
      }
    }
    if ((err && err.response && err.response.config && (!err.response.config.params || err.response.config.params.isShowErrorMsg !== false)) || err.code === 'ECONNABORTED') {

      // @ts-ignore
      Message.closeAll();
      Message.error(errMsg);
    }

    if (loadingInstance) {
      loadingInstance.close();
    }
    return Promise.reject(err.response);
  },
);

export default service;
